//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-08-18 22:49
 */
//========================================================================

#ifndef _LOGMANAGER_H_
#define _LOGMANAGER_H_
#include "Pre.h"

#include "config.h"
#include "DateTime.h"
#include "TimeValue.h"
#include "iniparser.h"
#include "ThreadMutex.h"

//
#define MAX_MODULE_NAME_LEN      255

//
#define ROOT_MODULE_NAME         "root"

// Generate file period stategy
enum
{
    GP_DISABLE  = 0,
    GP_HOURLY	= 1,
    GP_DAILY    = 2,
    GP_WEEKLY	= 3
};
// -----------------------------------------------------------------------
/**
 * @class LogManager
 *
 * @brief 
 */
class Logger;
class LogOutput;
class LogManager
{
public:
    ~LogManager ();

    // Singleton interface
    static LogManager *instance ();

    int init (const char *config_name);

    // 
    Logger *get_logger (const char *module_name);

    // log
    int log (Logger *log, int ll, const char *format, va_list &va_ptr);

protected:
    // Constructor 
    LogManager ();

    //
    int update_config (void);

    // Apply new configure.
    int apply_config (void);

    //
    int load_config (void);

    //
    int load_cfg_output (dictionary *ini);

    //
    int load_cfg_modules (dictionary *ini);

    //
    int load_cfg_strategy (dictionary *ini);

    //
    int load_cfg_lrecord (dictionary *ini);

    //
    int get_parent_llevel (const char *str, char *parent);

    //
    int apply_module_cfg (Logger *l);

    //
    int apply_strategy_cfg (void);

    //
    int insert_logger (Logger *l);

    //
    void dump_cfg (void);
public:
    class Output
    {
    public:
        enum
        {
            OM_NULL   = 0x0001,
            OM_STDOUT = 0x0002,
            OM_FILES  = 0x0004
        }output_t;

        static void reset (void);

        static int   output_mode_;
        static char *log_dir_;
    };
    class KeyValue
    {
    public:
        KeyValue ();
        ~KeyValue ();

        KeyValue &operator = (const KeyValue &kv);

        int   value;
        char *key;
    };
    class Modules
    {
    public:
        Modules ();

        ~Modules ();

        void reset (void);

        int insert (const char *module, int val);

        int get_llevel (const char *module);
    protected:
        int modules_num_; // The number of insert

        int list_size_;   // Buff size

        KeyValue *modules_list_;
    };
    class Strategy
    {
    public:
        Strategy ();

        void reset ();

        Strategy &operator = (const Strategy &s);

        int check_config_interval_;

        int generate_file_period_;

        int period_count_;

        int single_file_size_;

        int max_rolloever_index_;

        char file_name_[NDK_MAX_FILENAME_LEN + 1];
    };
    class LogRecord
    {
    public:
        LogRecord ();

        void reset ();

        int   max_len_of_one_record_;

        char  record_format_[128];
    };
private:
    // The size of <loggers>
    int curr_size_;

    // Store config file status
    struct stat st_buff_;

    //
    time_t last_check_time_;

    //
    time_t last_modify_time_;

    char *config_filename_;
    
    char *file_path_;

    // One log record buffer
    char *log_record_;

    Logger *root_node_;

    // Output 
    LogOutput *stdout_output_;

    LogOutput *files_output_;

    // = configure
    Strategy strategy_;

    Modules modules_;

    LogRecord lrecord_cfg_;

    // Time
    TimeValue current_time_;

    //
    DateTime  current_dtime_;

    ThreadMutex log_mutex_;

    char log_time_[64];
private:
    static LogManager *instance_;
};

#include "Post.h"
#endif

